#include "include.h"
#include "wireless.h"
#include "bsp_led.h"


#define MIC_ENC_BUFFER_SIZE         WIRELESS_MIC_FRAME_SIZE
#define MIC_DEC_BUFFER_SIZE         WIRELESS_MIC_FRAME_SIZE

#define MIC_DEC_OBUF_SIZE           (WIRELESS_MIC_SAMPLES_SELECT*WIRELESS_MIC_CHANNEL_SELECT*2)

///调速阈值，dac调速处于高跟低阈值的中间
#if WIRELESS_CON_CODEC_SEL == CODEC_LC3S
#define HIGH_SAMPLES_THR        (25*WIRELESS_CON_LINK_NB+16)
#define LOW_SAMPLES_THR         (25*WIRELESS_CON_LINK_NB+10)
#else
#define HIGH_SAMPLES_THR        (60*WIRELESS_CON_LINK_NB+16)
#define LOW_SAMPLES_THR         (60*WIRELESS_CON_LINK_NB+10)
#endif

typedef struct {
//    audio_callback_t callback;
    u8 frame[MIC_ENC_BUFFER_SIZE];
    bool kick_flag;
    uint8_t mute_en;                //控制mic端是否静音mute
} mic_enc_t;

typedef struct {
    audio_callback_t callback;
    u8 obuf[MIC_DEC_OBUF_SIZE];
    struct {
        u8 buf[MIC_DEC_OBUF_SIZE];
        u16 buf_cnt;
    } pcm[WIRELESS_CON_LINK_NB];

    u8 frame[MIC_DEC_BUFFER_SIZE];
    u8 last_bfi[WIRELESS_CON_LINK_NB];
    bool frag0_done_flag;
//    u8 fifo_sta;
} mic_dec_t;


static mic_enc_t mic_enc;
static mic_dec_t mic_dec;


//------------------------------------------------------------------------------------------
#define mic_enc_adc_get_sync(n)         bt_get_tick1_time(n)                                        //获取ADC采集偏差
#define mic_enc_adc_sync_proc()         bt_play_sync_tick1(0, WIRELESS_MIC_TX_INTERVAL*2)           //ADC采集偏差处理

////获取DAC播放偏差
//AT(.com_text.mic_dec)
//static void mic_dec_dac_get_sync(uint tick_cnt)
//{
//#if ADAPTER_DAC_OUTPUT_EN
//    bt_get_dac_fifocnt(tick_cnt);
//#endif
//}
//
////DAC播放偏差处理
//AT(.com_text.mic_dec)
//static void mic_dec_dac_sync_proc(void)
//{
//#if ADAPTER_DAC_OUTPUT_EN
//    if(mic_dec.fifo_sta == 0) {
//        dac_put_zero(10);
//        mic_dec.fifo_sta++;
//        return;
//    } else {
//        bt_play_sync_dac_fifocnt(120-30+16, WIRELESS_MIC_TX_INTERVAL/WIRELESS_MIC_COMB_NB*2);
//    }
//#endif
//}

//------------------------------------------------------------------------------------------
AT(.com_text.mic_enc)
void mic_enc_adc_dma_kick(uint tick_cnt)
{
    mic_enc_adc_get_sync(tick_cnt);

    if (wireless_cb.alg_en) {
#if !I2S_RX_AUDIO_EN
#if	!DEVICE_MIX_AUX_EN
        wireless_mic_kick();
#else
        wireless_mic_mix_aux_kick();
#endif
#endif
    }
#if I2S_RX_AUDIO_EN
    iis_rx_kick_soft_isr();
#endif
}

AT(.com_text.mic_enc)
void mic_enc_audio_input(u8 *pcm, u32 samples, int ch_mode, void *params)
{
//    GPIOBSET = BIT(1);
    if(wireless_cb.alg_en) {
        samples = WIRELESS_MIC_SAMPLES_SELECT;

        if(mic_enc.mute_en) {
            memset(pcm, 0x00, samples*2);
        }

#if (WIRELESS_CON_CODEC_SEL == CODEC_SBC)
        sbc_enc(pcm, mic_enc.frame, samples);
#elif  (WIRELESS_CON_CODEC_SEL == CODEC_LC3S)
        lc3s_enc((s16 *)pcm, mic_enc.frame, samples);
#endif
        wireless_d2a_put_tx_frame(mic_enc.frame, WIRELESS_MIC_FRAME_SIZE);
    }
//    GPIOBCLR = BIT(1);

#if !I2S_RX_AUDIO_EN
    mic_enc_adc_sync_proc();
#endif

//    //输出到下一级
//    if (mic_enc.callback) {
//        mic_enc.callback(ptr, WIRELESS_MIC_SAMPLES_SELECT, ch_mode, params);
//    }
}

AT(.text.mic_enc)
void mic_enc_audio_output_callback_set(audio_callback_t callback)
{
//    mic_enc.callback = callback;
}

AT(.text.mic_enc)
void mic_enc_init(u8 sample_rate, u16 samples)
{
    memset(&mic_enc, 0x00, sizeof(mic_enc));

//    mic_enc.callback = NULL;
}

void mic_enc_reset(void)
{
}

//------------------------------------------------------------------------------------------
AT(.com_text.mic_enc)
void mic_dec_dac_dma_kick(uint tick_cnt)
{
}

AT(.com_text.mic_enc)
void mic_dec_kick_cb(u8 idx)
{
    decoder_prio_trans_audio_input(NULL, WIRELESS_MIC_FRAME_SIZE, 1, &idx);
}

#if WIRELESS_CON_COMB_BUF_EN
void mic_dec_pcm_out(u8 idx)
{
    s16 *obuf = (s16 *)mic_dec.obuf;
    u8 samples = WIRELESS_MIC_SAMPLES_SELECT/2;

    mic_dec.pcm[idx].buf_cnt = 0;                   //复位pcm[idx].buf_cnt，确保先copy前半段pcm[idx].buf

    s16 *pcm0 = (s16 *)(mic_dec.pcm[0].buf + mic_dec.pcm[0].buf_cnt);
    s16 *pcm1 = (s16 *)(mic_dec.pcm[1].buf + mic_dec.pcm[1].buf_cnt);

#if ADAPTER_MIX_DRC_EN
    mix_drc_audio_input(pcm0, pcm1, obuf, samples);
#else
    for(uint i=0; i<samples; i++) {
        obuf[i] = pcm0[i]/2 + pcm1[i]/2;
    }
#endif

    mic_dec.pcm[0].buf_cnt += MIC_DEC_OBUF_SIZE/2;
    if(mic_dec.pcm[0].buf_cnt >= MIC_DEC_OBUF_SIZE) {
        mic_dec.pcm[0].buf_cnt = 0;
    }
    mic_dec.pcm[1].buf_cnt += MIC_DEC_OBUF_SIZE/2;
    if(mic_dec.pcm[1].buf_cnt >= MIC_DEC_OBUF_SIZE) {
        mic_dec.pcm[1].buf_cnt = 0;
    }

    //输出到下一级
    if (mic_dec.callback) {
        mic_dec.callback((void *)obuf, samples, 1, NULL);
    }
}
#else // WIRELESS_CON_COMB_BUF_EN

#if (WIRELESS_CON_LINK_NB > 1)
AT(.com_text.mic_dec)
static uint16_t mic_dec_us_trans_samples(uint16_t us, uint8_t spr_idx)
{
    uint16_t samples_duration = 0;

    switch(spr_idx) {
        ///对应48k采样率的情况，一个样点对应20.8us
        case SAMPLE_RATE_48K:
            samples_duration = 21;
            break;

        ///对应16k采样率的情况，一个样点对应62.5us
        case SAMPLE_RATE_16K:
            samples_duration = 62;
            break;

        default:
            samples_duration = 21;
            break;
    }

    return (us/samples_duration);
}

AT(.com_text.mic_dec)
static void mic_dec_pcm_out_samples(s16 *pcm0, s16 *pcm1, uint8_t samples, uint8_t adj_dac_flag)
{
    s16 *obuf = (s16 *)mic_dec.obuf;

#if ADAPTER_MIX_DRC_EN
    mix_drc_audio_input(pcm0, pcm1, obuf, samples);
#else
    for(uint i=0; i<samples; i++) {
        obuf[i] = pcm0[i]/2 + pcm1[i]/2;
    }
#endif

    //输出到下一级
    if (mic_dec.callback) {
        mic_dec.callback((void *)obuf, samples, 1, NULL);
    }
}

AT(.com_text.mic_dec)
static void mic_dec_pcm_out_frag0(u8 dec_flag)
{
    uint8_t frag0_samples = mic_dec_us_trans_samples(ble_t2r_v3_link_duration_get(0), WIRELESS_MIC_SAMPLE_RATE_SELECT);

    s16 *pcm0 = (s16 *)(&mic_dec.pcm[0].buf[0]);
    s16 *pcm1 = (s16 *)(&mic_dec.pcm[1].buf[0]) + (WIRELESS_MIC_SAMPLES_SELECT-frag0_samples);

    mic_dec_pcm_out_samples(pcm0, pcm1, frag0_samples, dec_flag);
}

//format pcm / upsample / mix
AT(.com_text.mic_dec)
static void mic_dec_pcm_out_frag1(u8 dec_flag)
{
    uint8_t frag0_samples = mic_dec_us_trans_samples(ble_t2r_v3_link_duration_get(0), WIRELESS_MIC_SAMPLE_RATE_SELECT);
    uint8_t frag1_samples = WIRELESS_MIC_SAMPLES_SELECT - frag0_samples;

    s16 *pcm0 = (s16 *)(&mic_dec.pcm[0].buf[0]) + frag0_samples;
    s16 *pcm1 = (s16 *)(&mic_dec.pcm[1].buf[0]);

    mic_dec_pcm_out_samples(pcm0, pcm1, frag1_samples, dec_flag);
}
#endif

AT(.com_text.mic_dec)
static void mic_dec_pcm_out(u8 idx)
{
#if (WIRELESS_CON_LINK_NB == 1)
    //输出到下一级
    if (mic_dec.callback) {
        mic_dec.callback((void *)(&mic_dec.pcm[idx].buf[0]), WIRELESS_MIC_SAMPLES_SELECT, 1, NULL);
    }
#else
    u8 con_status;
    u8 dec_flag = 0;

    if(idx == 0) {
        if (mic_dec.frag0_done_flag == 0) {
            //推通道1前半帧+通道2后半帧
            mic_dec_pcm_out_frag0(dec_flag);
            mic_dec.frag0_done_flag = 1;
        }

        //若通道2未连接，把frag1也转换了
        con_status = ble_con_get_status();
        if((con_status & ~BIT(idx)) == 0) {
            mic_dec_pcm_out_frag1(0);
            mic_dec.frag0_done_flag = 0;
        }
    } else {
        //通道2解码完，再转换frag1，输出到OBUF后半段
        if(mic_dec.frag0_done_flag) {
            mic_dec_pcm_out_frag1(dec_flag);
            mic_dec.frag0_done_flag = 0;
        }

        //若通道1未连接，把frag0也转换了
        con_status = ble_con_get_status();
        if((con_status & ~BIT(idx)) == 0) {
            mic_dec_pcm_out_frag0(0);
            mic_dec.frag0_done_flag = 1;
        }
    }
#endif
}
#endif // WIRELESS_CON_COMB_BUF_EN

AT(.com_text.mic_dec)
void mic_dec_audio_input(u8 *ptr, u32 samples, int ch_mode, void *params)
{
    u8 idx = *(u8 *)params;

#if WARNING_TONE_EN
    //mp3 提示音功能使用过程中pass解码流程
    if(res_music_playing_state_get()){
        return;
    }
#endif

    s16 *pcm = (s16 *)&mic_dec.pcm[idx].buf;
    samples = WIRELESS_MIC_SAMPLES_SELECT;

    if(wireless_cb.alg_en) {
        u8 con_status = ble_con_get_status();
        if(con_status & BIT(idx)) {
            bool bfi = wireless_d2a_get_rx_frame(idx, mic_dec.frame, WIRELESS_MIC_FRAME_SIZE);

//            GPIOBSET = BIT(1);
            if(!bfi) {
#if (WIRELESS_CON_CODEC_SEL == CODEC_LC3S)
                lc3s_dec(mic_dec.frame, pcm, samples, idx);
#elif (WIRELESS_CON_CODEC_SEL == CODEC_SBC)
                sbc_dec(mic_dec.frame, pcm, samples, idx);
#endif
            }

            plc_soft_process(pcm, samples, mic_dec.last_bfi[idx]||bfi, idx);
            mic_dec.last_bfi[idx] = bfi;
//            GPIOBCLR = BIT(1);
        }
    } else {
        memset(pcm, 0x00, samples*2);
    }

#if !ADAPTER_AUX_TX_EN
    if (1) {
        uint16_t high_samples_thr = HIGH_SAMPLES_THR;
        uint16_t low_samples_thr  = LOW_SAMPLES_THR;
//魔音算法使能 阈值放大24  48*0.5
#if ADAPTER_ECHO_EN || ADAPTER_MAGIC_EN
        high_samples_thr += 24;
        low_samples_thr  += 24;
#endif

#if ADAPTER_MIC_DRC_EN  //120个点处理时间 450us
        high_samples_thr += 48;
        low_samples_thr  += 48;
#endif // ADAPTER_MIC_DRC_EN

#if ADAPTER_AINS3_EN
        high_samples_thr += 360;
        low_samples_thr  += 360;
#endif
        dac_out_adj_phase(high_samples_thr, low_samples_thr);
    }
#endif

    mic_dec_pcm_out(idx);
}

AT(.com_text.mic_dec)
void mic_dec_buf_clr(u8 idx)
{
    memset(mic_dec.pcm[idx].buf, 0x00, MIC_DEC_OBUF_SIZE);
}

AT(.text.mic_dec)
void mic_dec_audio_output_callback_set(audio_callback_t callback)
{
    mic_dec.callback = callback;
}

AT(.text.mic_dec)
void mic_dec_init(u8 sample_rate, u16 samples)
{
    memset(&mic_dec, 0x00, sizeof(mic_dec));

//    mic_dec.callback = NULL;
}

void mic_dec_reset(u8 idx)
{
    mic_dec.last_bfi[idx] = 0;
    memset(mic_dec.pcm[idx].buf, 0, MIC_DEC_OBUF_SIZE);
}


